import type { Rule } from 'ant-design-vue/es/form'

/**
 * 检查输入值是否为仅包含汉字、英文字母和数字的字符串
 * @param {Rule} _rule - 表单项传入的规则对象。
 * @param {string} value - 正在验证的字段的值。
 * @returns 返回承诺的函数。
 */
export const validateChineseLetterNumber = async (
  _rule: Rule,
  value: string
) => {
  const pattern = /^[a-zA-Z0-9\u4e00-\u9fa5]+$/ // 匹配汉字、英文字母和数字的正则表达式
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('仅支持汉字/英文/数字字符输入'))
  }
  await Promise.resolve()
}

export const validateOnlyChineseUnicode = async (
  _rule: Rule,
  value: string
) => {
  const pattern = /^[a-zA-Z-_0-9\u4e00-\u9fa5]+$/
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(
      new Error('仅支持输入中文/英文/数字/下划线/中划线')
    )
  }
  await Promise.resolve()
}

/**
 * 检查输入密码长度至少8位，最长16位，输入的密码内容至少包含“数字”、“大写字母”、“小写字母”、“字符”其中两种
 * @param {Rule} _rule - 正在验证的规则对象。
 * @param {string} value - 正在验证的字段的值。
 * @returns 返回承诺的函数。
 */
export const validatePasswordStrength = async (_rule: Rule, value: string) => {
  // 密码不能为空
  if (value === '') {
    return await Promise.reject(new Error('密码不能为空'))
  }

  // 密码长度至少8位，最长16位
  if (value.length < 8 || value.length > 16) {
    return await Promise.reject(new Error('密码长度应为8-16位'))
  }

  // 判断密码中是否包含数字、大写字母、小写字母、字符四种类型中的至少两种
  const types = [
    /\d/, // 包含数字
    /[A-Z]/, // 包含大写字母
    /[a-z]/, // 包含小写字母
    /[^A-Za-z0-9]/ // 包含字符（非字母或数字）
  ]
  let count = 0
  for (let i = 0; i < types.length; i++) {
    if (types[i].test(value)) {
      count++
    }
  }
  if (count < 2) {
    return await Promise.reject(
      new Error('密码应包含数字、大写字母、小写字母、字符中的至少两种')
    )
  }

  // 如果通过了上述验证，则说明密码符合要求
  await Promise.resolve()
}

/**
 * 此函数验证字符串是否仅包含字母、数字和下划线。
 * @param {Rule} rule - 一个验证规则对象，其中包含有关应用于输入值的验证规则的信息。
 * @param {string} value - 要根据正则表达式模式验证的值。在这种情况下，它应该只包含字母（大写和小写）、数字和下划线。
 * @returns 正在返回一个 Promise。如果该值与指定的模式不匹配，则返回带有错误消息的被拒绝的 Promise。如果该值与模式匹配，则返回已解决的 Promise。
 */
export const validateLetterNumberUnderscore = async (
  _rule: Rule,
  value: string
) => {
  const pattern = /^[a-zA-Z0-9_]+$/ // 匹配英文字母、数字和下划线的正则表达式
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('仅支持输入英文、数字、下划线'))
  }
  await Promise.resolve()
}

export const validateLetterNumberPoint = async (_rule: Rule, value: string) => {
  const pattern = /^[a-zA-Z0-9.]+$/ // 匹配英文字母、数字和点的正则表达式
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('仅支持输入英文/数字/点'))
  }
  await Promise.resolve()
}

export const validateUrl = async (_rule: Rule, value: string) => {
  const pattern = /^(http[s]?:\/\/.*|mailto:|tel:)/ // 匹配网址的正则表达式
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('请输入合法的网址'))
  }
  await Promise.resolve()
}

/**
 * 此函数验证给定的字符串输入是否为最多 3 位小数的正数。
 * @param {Rule} _rule - 此参数表示应用于输入值的验证规则。它不用于函数的实现，但包含在内是为了与可能使用此函数的验证库兼容。
 * @param {string} value - 需要验证的值，应该是一个字符串，代表一个小数点后最多3位的数字。
 * @returns 如果该值不为空且与指定的模式不匹配，将返回带有错误消息的被拒绝的 Promise。否则，将返回已解决的 Promise。
 */
export const validateNumberWithDecimal = async (_rule: Rule, value: string) => {
  const pattern = /^\d+(.\d{1,3})?$/ // 匹配数字和小数点，小数点最多3位小数
  if (value !== null && value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('只能输入正数，最多3位小数'))
  }
  await Promise.resolve()
}
/**
 * 此函数验证给定的字符串输入是否仅包含数字和小数点。
 * @param {Rule} _rule - 此参数表示应用于输入值的验证规则。它不用于函数的实现。
 * @param {string} value - 需要验证的值，它应该是一个字符串，代表一个带有可选小数点的数字。
 * @returns 正在返回一个 Promise。如果该值不是带小数点的有效数字，则 Promise 将被拒绝并显示错误消息。如果该值有效，则 Promise 将被解决。
 */
export const validateOnlyNumberDecimal = async (_rule: Rule, value: string) => {
  const pattern = /^\d+(.\d+)?$/ // 匹配数字和小数点，小数点可以出现 0 次或 1 次
  if (
    value !== undefined &&
    value !== '' &&
    value !== null &&
    !pattern.test(value)
  ) {
    return await Promise.reject(new Error('只能输入数字和小数点'))
  }
  await Promise.resolve()
}

/**
 * 这是一个 TypeScript 函数，用于验证给定值是否为空。
 * @param {Rule} _rule - 此参数属于“Rule”类型，未在函数中使用。它可能用于调用“validateEmpty”作为辅助函数的更大的验证函数。
 * @param {string} value - 要验证是否为空的值。
 * @returns 如果 `value` 参数为 `undefined` 或空字符串，则返回带有“请输入”错误信息的拒绝承诺。否则，将返回已解决的承诺。
 */
export const validateEmpty = async (_rule: Rule, value: string) => {
  if (value === undefined || value === '' || value === null) {
    return await Promise.reject(new Error('请输入'))
  }
  await Promise.resolve()
}

/**
 * 此 TypeScript 函数从给定字符串中删除特殊字符。
 * @param {string} str - 需要处理以去除特殊字符的输入字符串。
 * @returns 函数 `removeSpecialChars` 将字符串作为输入并删除任何特殊字符（包括 `%`、`!`、`[`、`]`、`*`、`^`、`/`、`'`、` "`, `;`,
 * `\`) 从它使用正则表达式。然后该函数返回修改后的字符串，其中删除了特殊字符。
 */
export function removeSpecialChars(str: string) {
  // eslint-disable-next-line no-useless-escape
  return str.replace(/[%!\[\]*^\/'";\\]/g, '')
}

/**
 * 此函数使用正则表达式模式验证给定字符串是否为有效的 IPv4 地址。
 * @param {Rule} _rule - 此参数是 Rule 类型，用于表单中的验证规则。它不用于函数的实现。
 * @param {string} value - 要验证的值，应该是表示 IPv4 地址的字符串。
 * @returns 如果该值不是有效的 IPv4 地址，则返回一个 Promise 并拒绝并显示错误消息“请输入合法的 IPv4 地址”（中文意思是“请输入有效的 IPv4
 * 地址”）。如果该值有效或为空，则返回已解决的 Promise。
 */
export const validateIPv4Address = async (_rule: Rule, value: string) => {
  const pattern =
    /^((25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/ // IPv4地址的正则表达式
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('请输入合法的IPv4地址'))
  }
  await Promise.resolve()
}

/**
 * 此函数验证给定的密码字符串是否仅包含允许的特殊字符。
 * @param {Rule} _rule - 此参数表示应用于输入值的验证规则。它可能包含其他信息，例如输入的最小和最大长度、所需格式等。
 * @param {string} value - 要验证的值，它是一个表示密码的字符串。
 * @returns `validateSpecialPassword` 函数返回一个 Promise，该 Promise 要么通过 Error 对象解决，要么拒绝。如果输入值与允许的模式不匹配，则
 * Promise 将被拒绝，并显示一条指示允许字符的错误消息。如果输入值有效，则 Promise 将被解析为无值。
 */
export const validateSpecialPassword = async (_rule: Rule, value: string) => {
  const pattern = /^[a-zA-Z0-9_+-.?$#@!]*$/ // 匹配允许的特殊字符
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(
      new Error(
        '只能输入英文大小写字母、数字、“_”、“+”、“-”、“.”、“?”、“$”、“#”、“@”、“!”'
      )
    )
  }
  await Promise.resolve()
}

export const validateOnlyNumber = async (_rule: Rule, value: string) => {
  const pattern = /^[0-9]+$/ // 匹配数字的正则表达式
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('仅支持输入数字'))
  }
  await Promise.resolve()
}

export const validatePort = async (_rule: Rule, value: string) => {
  const pattern =
    /^[1-9]\d{0,3}$|^[1-5]\d{4}$|^[6][0-4]\d{3}$|^[6][5][0-4]\d{2}$|^[6][5][5][0-2]\d$|^[6][5][5][3][0-5]$/
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('请输入合法的端口号'))
  }
  await Promise.resolve()
}

export const isNumber = async (_rule: Rule, value: string) => {
  const pattern = /^-?\d+(\.\d+)?$/
  if (value !== '' && !pattern.test(value)) {
    return await Promise.reject(new Error('请输入正确的数字'))
  }
  await Promise.resolve()
}

export const isPositiveInteger = async (_rule: Rule, value: string) => {
  const pattern = /^[1-9]\d*$/
  if (
    value !== undefined &&
    value !== null &&
    value !== '' &&
    !pattern.test(value)
  ) {
    return await Promise.reject(new Error('请输入正整数'))
  }
}

// 不能大于720
export const cannotBeGreaterThan720 = async (_rule: Rule, value: string) => {
  if (value !== '' && Number(value) > 720) {
    return await Promise.reject(new Error('不能大于720'))
  }
  await Promise.resolve()
}

export const validateNumberWithDecimalTwo = async (
  _rule: Rule,
  value: string | undefined
) => {
  const pattern = /^-?(?!0+(?:\.0+)?$)\d+(\.\d{1,2})?$/ // 匹配数字和小数点，小数点最多2位小数
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
  if (value && !pattern.test(value)) {
    return await Promise.reject(
      new Error('请输入不为0的数值，最多保留两位小数')
    )
  }
  await Promise.resolve()
}

// eslint-disable-next-line
export const specialCharsReg = /[%!\[\]*^\/\'\";\\\‘\’\!\“\”\；\、！\【\】\*\、]/g